package com.klikmee.sms.chat.web.senders;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;

import com.klikmee.sms.cef.CoreAdapter;
import com.klikmee.sms.cef.services.Service;
import com.klikmee.sms.chat.web.dao.AnswerDAO;
import com.klikmee.sms.services.chat.model.Answer;
import com.klikmee.sms.services.chat.model.Question;

/**
 * ********************************************************************************
 * <p>
 * This impl of {@link MessageSender} uses 2 service instances to send messages. Used to simulate bulk messaging like following:
 * </p>
 * <p>
 * First chunk of the message is send via the first service and charged to the user. Other parts (if any) are send via second service impl and are free of charge for the user.
 * </p>
 * 
 * @author makcro
 ********************************************************************************* 
 * 
 */
public class DualServiceMessageSenderImpl implements MessageSender {

	/**
	 * Logger instance
	 */
	private Logger logger = Logger.getLogger(DualServiceMessageSenderImpl.class);

	/**
	 * {@link CoreAdapter} instance used to send messages via core platform.
	 */
	private CoreAdapter coreAdapter = null;

	/**
	 * Charging service settings
	 */
	private Long chargingId = null;
	private Long chargingServiceId = null;
	/**
	 * Bulk service settings
	 */
	private Long bulkChargingId = null;
	private Long bulkServiceId = null;

	private AnswerDAO answerDAO = null;

	/**
	 * Sends charging message by splitting it on 160 and 153 character chunks.
	 * 
	 * @param messageText
	 *            message to send
	 * @param coreReferenceId
	 *            reference id of the initial end user's request.
	 * @return number of parts sent
	 */
	@Override
	public int sendMessage(String messageText, Long coreReferenceId, Object data) {

		// expect Question as additional data
		Question question = (Question) data;

		// check if this is a long message and split it into smaller chunks
		List<String> messageParts = splitMessage(messageText);

		// send the firs part via charging service
		String firstPart = messageParts.get(0);
		Long chargedCoreRefId = coreAdapter.sendMessage(this.chargingId, this.chargingServiceId, Service.SERVICE_FLAG_SEMANTIC_OK, coreReferenceId, firstPart);
		persistAnswer(question, firstPart, chargedCoreRefId);

		// if there are others, send them via bulk service
		if (messageParts.size() > 1) {
			for (String currentPart : messageParts) {
				Long currentPartCoreRefId = coreAdapter.sendMessage(chargedCoreRefId, chargingServiceId, Service.SERVICE_FLAG_SEMANTIC_OK, coreReferenceId, currentPart);
				persistAnswer(question, currentPart, currentPartCoreRefId);
			}
		}

		return messageParts.size();
	}

	/**
	 * Persists {@link Answer} object into database
	 * 
	 * @param question
	 * @param messageText
	 * @param refCoreId
	 */
	private void persistAnswer(Question question, String messageText, Long refCoreId) {
		Answer answer = new Answer();
		answer.setAnswer(messageText);
		answer.setCoreID(refCoreId);
		answer.setDateAnswered(new Date());
		answer.setFromNumber(question.getToNumber());
		answer.setQuestion(question);
		answer.setToNumber(question.getFromNumber());
		answer.setVisable(true);

		this.answerDAO.create(answer);

	}

	/**
	 * Splits message into long messge chunks
	 * 
	 * @param longMessage
	 *            complete message text
	 * @return list of message chunks
	 */
	public List<String> splitMessage(String longMessage) {
		ArrayList<String> parts = new ArrayList<String>();
		int partSize = 160;
		// characters total
		int messageLength = longMessage.length();
		// index of last split
		int delimiter = 0;
		int rest = messageLength - delimiter;
		// if rest of the message is bigger then part size, then split the rest
		// and move delimiter
		while (rest > partSize) {
			String part = longMessage.substring(delimiter, delimiter + partSize);
			parts.add(part);
			// decrement part size to fit other segments
			partSize = 153;
			delimiter += partSize;
			rest = messageLength - delimiter;
		}
		// if the rest is bigger then 0 then add it as final part
		if (rest > 0) {
			String finalPart = longMessage.substring(delimiter);
			parts.add(finalPart);
		}

		return parts;
	}

	public void setCoreAdapter(CoreAdapter coreAdapter) {
		this.coreAdapter = coreAdapter;
	}

	public void setChargingId(Long chargingId) {
		this.chargingId = chargingId;
	}

	public void setChargingServiceId(Long chargingServiceId) {
		this.chargingServiceId = chargingServiceId;
	}

	public void setAnswerDAO(AnswerDAO answerDAO) {
		this.answerDAO = answerDAO;
	}

	public void setBulkChargingId(Long bulkChargingId) {
		this.bulkChargingId = bulkChargingId;
	}

	public void setBulkServiceId(Long bulkServiceId) {
		this.bulkServiceId = bulkServiceId;
	}

}
